/**
 * 分页的构造函数
 * @param {String|Document} elem 实现显示分页的容器的dom对象 或者样式
 * @param {Object} options 分页的参数配置 控制分页功能
 */
function Page(elem, options, callback) {
    // 使用对象属性保存回调函数
    this.callback = callback
    // 使用属性保存着容器的dom对象
    this.elem = (Object.prototype.toString.call(elem) == '[object String]') ? document.querySelector(elem) : elem;
    // 保存存储数字页容器的dom对象
    this.listDom = null;
    // 保存输入文本框的dom对象
    this.inputDom = null;
    // 默认的配置
    this.config = {
        // 控制显示的文本
        language: {
            first: '<<',
            prev: '<',
            list: '',
            next: '>',
            last: '>>'
        },
        // 控制显示的数据量 用于后期生成数字
        data: {
            total: 100, //数据总条数
            pageSize: 10 //每一页显示的数量
        }
    }
    // 进行默认参数的合并 将用户传递的有用的参数对默认的进行覆盖
    this.mergeConfig(options);
    // 计算总页数
    this.totalPage = Math.ceil(this.config.data.total / this.config.data.pageSize);
    // 保存当前在那一页
    this.currentPage = 1;
    this.init();
    // 调用方法完成点击事件委托
    this.executeEvent();
}
// 添加事件委托处理点击事件
Page.prototype.executeEvent = function () {
    // 如果是普通的function 点击事件中this表示的是dom对象 箭头函数中this 表示的是上层的this的对象
    this.elem.addEventListener('click', event => {
        switch (event.target.className) {
            case 'first':
                // 表示的是点击的是首页
                this.currentPage = 1;
                this.init();
                break;
            case 'prev':
                // 判断是为了避免在第一页时继续上一页 将当前页设置为负数
                if (this.currentPage > 1) {
                    this.currentPage -= 1;
                    this.init();
                }
                break;
            case 'next':
                if (this.currentPage < this.totalPage) {
                    this.currentPage += 1;
                    this.init();
                }
                break;
            case 'last':
                this.currentPage = this.totalPage;
                this.init();
                break;
            default:
                // 判断点击的是不是P标签上的数字
                if (event.target.nodeName == 'P') {
                    this.currentPage = Number(event.target.innerHTML);
                    this.init();
                } else if (event.target.nodeName == 'BUTTON') {
                    // 获取到当前输入的值
                    let num = parseInt(this.inputDom.value);
                    if (num > 0 && num < this.totalPage) {
                        this.currentPage = num;
                        this.init();
                    }
                }
        }

    })
}

// 原型上增加启动方法
Page.prototype.init = function () {
    this.elem.innerHTML = '';
    this.createOutside();
    this.createNumber();
    // 显示输入数字跳转文本框
    this.createJumpElement();
    // 每次执行到init函数 绝对表示当前页在被修改
    // 调用函数传递实参
    Object.prototype.toString.call(this.callback) == '[object Function]' && this.callback(this.currentPage);
}

Page.prototype.createJumpElement = function () {
    // 创建输入的文本框
    this.inputDom = document.createElement('input');
    this.inputDom.style.width = '60px'
    this.inputDom.style.marginRight = '10px'
    this.elem.appendChild(this.inputDom);
    // 创建按钮
    let btnDom = document.createElement('button');
    btnDom.innerHTML = 'Jump';
    this.elem.appendChild(btnDom)
}

// 生成指定区间的数字页
Page.prototype.createNumberRandom = function (start, end) {
    for (let i = start; i <= end; i++) {
        let pDom = document.createElement('p');
        // 第一个p标签加上特殊的样式
        i == this.currentPage && (pDom.className = 'active')
        pDom.innerHTML = i;
        this.listDom.appendChild(pDom);
    }
}
// 创建数字页
Page.prototype.createNumber = function () {
    if (this.totalPage <= 5) {
        // 总页数小于等于5 永远显示 1-总页数
        this.createNumberRandom(1, this.totalPage);
    } else {
        if (this.currentPage <= 3) {
            // 当前页小于等于3 显示的永远是1-5之间的数字
            this.createNumberRandom(1, 5);
        } else if (this.currentPage >= this.totalPage - 2) {
            // 当前页大于等于总页数-2 显示最后5个数字
            this.createNumberRandom(this.totalPage - 4, this.totalPage);
        } else {
            // 当前页 大于3 并且小于总页数-2  显示当前页 以及前面2个数字 当前页后面2个数字
            this.createNumberRandom(this.currentPage - 2, this.currentPage + 2);
        }
    }
}
// 原型上添加创建外层div的方法
Page.prototype.createOutside = function () {
    for (let key in this.config.language) {
        let divDom = document.createElement('div');
        // 设置样式名称 后期用户需要针对分页进行样式控制 可以自己根据样式名称编写样式
        divDom.className = key;
        divDom.innerHTML = this.config.language[key];
        // 如果是存储数字页的容器使用对象属性保存 保存的目的是为了方便后期使用(避免在页面上寻找list的元素)
        key == 'list' && (this.listDom = divDom);
        this.elem.appendChild(divDom)
    }
}

// 原型增加合并参数方法
Page.prototype.mergeConfig = function (options) {
    // 需要使用用户传递的覆盖默认的配置项
    // 处理显示上一页、下一页的文本配置
    for (let key in this.config.language) {
        // 检查当前循环key对应的属性 用户是否有传递，如果传递 就覆盖默认值
        options.language[key] && (this.config.language[key] = options.language[key])
    }

    // 处理数据的数量
    for (let key in this.config.data) {
        // 检查当前循环key对应的属性 用户是否有传递，如果传递 就覆盖默认值
        options.data[key] && (this.config.data[key] = options.data[key])
    }
}